package com.wecan.components.sms.service;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20190711.SmsClient;
import com.tencentcloudapi.sms.v20190711.models.SendStatus;
import com.wecan.base.constants.RedisKey;
import com.wecan.cache.utils.RedisUtil;
import com.wecan.components.sms.constant.SmsTemplateType;
import com.wecan.components.sms.properties.AliSMSProperties;
import com.wecan.components.sms.properties.TencentSMSProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.Random;

/**
 * @Author liuzhihao
 * @Date 2022.02.16
 * @Version ${version}
 * @Description ${description}
 */
@Slf4j
public class SMSService {

    @Autowired
    private AliSMSProperties aliSMSProperties;

    @Autowired
    private TencentSMSProperties tencentSMSProperties;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 生成短息验证码
     * @return
     */
    private String generateCode() {
        int n = 6;
        StringBuilder code = new StringBuilder();
        Random ran = new Random();
        for (int i = 0; i < n; i++) {
            code.append(Integer.valueOf(ran.nextInt(10)).toString());
        }
        return code.toString();
    }

    /**
     * 创建阿里云客户端
     * @return
     */
    private IAcsClient createAliClient() {
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", aliSMSProperties.getAccessKey(), aliSMSProperties.getAccessSecret());
        IAcsClient client = new DefaultAcsClient(profile);
        return client;
    }

    /**
     * 创建腾讯短信客户端
     * @return
     */
    private SmsClient createTencentClient() {
        Credential credential = new Credential(tencentSMSProperties.getAccessKey(), tencentSMSProperties.getAccessSecret());
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setReqMethod("POST");
        httpProfile.setConnTimeout(60);
        httpProfile.setEndpoint("sms.tencentcloudapi.com");
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setSignMethod("HmacSHA256");
        clientProfile.setHttpProfile(httpProfile);
        return new SmsClient(credential, "ap-nanjing", clientProfile);
    }

    /**
     * 创建短信请求体
     * @param phoneNum
     * @param templateCode
     * @param templateParam
     * @return
     */
    private SendSmsRequest createAliSmsReqeust(String phoneNum, String templateCode, String templateParam) {
        SendSmsRequest sendSmsRequest = new SendSmsRequest();
        sendSmsRequest.setSignName(aliSMSProperties.getSignName());
        sendSmsRequest.setTemplateCode(templateCode);
        if (templateParam != null) {
            sendSmsRequest.setTemplateParam(templateParam);
        }
        sendSmsRequest.setPhoneNumbers(phoneNum);
        return sendSmsRequest;
    }

    /**
     * 生成短信请求
     * @param phoneNum
     * @param templateCode
     * @param templateParam
     * @return
     */
    private com.tencentcloudapi.sms.v20190711.models.SendSmsRequest createTencentSmsRequest(String phoneNum, String templateCode, String templateParam) {
        com.tencentcloudapi.sms.v20190711.models.SendSmsRequest sendSmsRequest = new com.tencentcloudapi.sms.v20190711.models.SendSmsRequest();
        sendSmsRequest.setSmsSdkAppid(tencentSMSProperties.getAppId());
        sendSmsRequest.setSign(tencentSMSProperties.getSignName());
        sendSmsRequest.setTemplateID(templateCode);
        String[] phoneNumberSet = {"+86" + phoneNum};
        sendSmsRequest.setPhoneNumberSet(phoneNumberSet);
        String[] templateParamSet = {templateParam};
        sendSmsRequest.setTemplateParamSet(templateParamSet);
        return sendSmsRequest;
    }

    /**
     * 发送短息验证码
     * @return
     */
    public boolean sendSmsCode(String phoneNum) {
        if ("local".equals(aliSMSProperties.getAccessKey())) {
            redisUtil.set(RedisKey.PHONE_VALIDATE_CODE + phoneNum, "123456", RedisKey.PHONE_VALIDATE_CODE_EXPIRE_TIME);
            return true;
        }
        if (StringUtils.isNotEmpty(aliSMSProperties.getAccessKey())) {
            IAcsClient client = createAliClient();
            HashMap<String, String> templateParam = new HashMap<>();
            String code = generateCode();
            templateParam.put("code", code);
            SendSmsRequest sendSmsRequest = createAliSmsReqeust(phoneNum, SmsTemplateType.ALI_VERIFY_CODE, JSONObject.toJSONString(templateParam));
            try {
                SendSmsResponse acsResponse = client.getAcsResponse(sendSmsRequest);
                if ("OK".equals(acsResponse.getCode())) {
                    redisUtil.set(RedisKey.PHONE_VALIDATE_CODE + phoneNum, code, RedisKey.PHONE_VALIDATE_CODE_EXPIRE_TIME);
                    return true;
                }
                return false;
            } catch (ServerException e) {
                return false;
            } catch (ClientException e) {
                return false;
            }
        } else if (StringUtils.isNotEmpty(tencentSMSProperties.getAccessKey())) {
            SmsClient tencentClient = createTencentClient();
            String code = generateCode();
            com.tencentcloudapi.sms.v20190711.models.SendSmsRequest tencentSmsRequest = createTencentSmsRequest(phoneNum, SmsTemplateType.TENCENT_VERIFY_CODE, code);
            try {
                com.tencentcloudapi.sms.v20190711.models.SendSmsResponse sendSmsResponse = tencentClient.SendSms(tencentSmsRequest);
                SendStatus[] sendStatusSet = sendSmsResponse.getSendStatusSet();
                SendStatus sendStatus = sendStatusSet[0];
                if (sendStatus != null && "Ok".equals(sendStatus.getCode())) {
                    redisUtil.set(RedisKey.PHONE_VALIDATE_CODE + phoneNum, code, RedisKey.PHONE_VALIDATE_CODE_EXPIRE_TIME);
                    return true;
                }
                return false;
            } catch (TencentCloudSDKException e) {
                return false;
            }
        }
        return false;
    }
}
